using System;
using System.Collections.Generic;
using System.Text;

using SlimDX;
using SlimDX.Direct3D9;
using SlimDX.Windows;

using miciv.Geometry;
using miciv.Misc;

namespace miciv.Rendering
{
    public class RendererBase : IRenderer
    {
        protected FowardReserveList<IRenderable> m_lstRenderables;
        protected Effect m_effect;
        protected EffectHandle m_hTechnique;
        protected VertexDeclaration m_vertexDecl;
        protected int m_sPasses;
        protected List<string> m_lstSupportedVertexFormats;
        protected IRendererContext m_rendererContext;

        public RendererBase()
        {
            this.m_lstRenderables = new FowardReserveList<IRenderable>();
            this.m_lstSupportedVertexFormats = new List<string>();
        }

        static protected int SortByIncreasingZOrder(IRenderable _renderable1, IRenderable _renderable2)
        {
            if (_renderable2 == _renderable1)
            {
                return 0;
            }
            if (null == _renderable1)
            {
                return -1;
            }
            if (null == _renderable2)
            {
                return 1;
            }
            if (_renderable1.World.M43 > _renderable2.World.M43)
            {
                return 1;
            }
            if (_renderable1.World.M43 < _renderable2.World.M43)
            {
                return -1;
            }
            return 0;
        }

        #region IRenderer Membres

        virtual public bool HasPendingRenderables
        {
            get
            {
                return (0 < this.m_lstRenderables.Capacity);
            }
        }

        public IRendererContext RendererContext
        {
            get
            {
                return this.m_rendererContext;
            }
            set
            {
                this.m_rendererContext = value;
            }
        }

        virtual public bool CanSupportVertexDefinition(VertexDefinition _vertexFormat)
        {
            return false;
        }

        virtual public bool CanSupportRenderable(IRenderable _renderable)
        {
            return false;
        }

        virtual public bool CanSupportRenderableType(Type _type)
        {
            return false;
        }

        virtual public void Add(IRenderable _renderable)
        {
            if (false == this.m_lstRenderables.Contains(_renderable))
            {
                this.m_lstRenderables.Add(_renderable);
            }
        }

        virtual public void Remove(IRenderable _renderable)
        {
            if (false != this.m_lstRenderables.Contains(_renderable))
            {
                this.m_lstRenderables.Remove(_renderable);
            }
        }

        virtual public void BeginScene()
        {
            this.m_lstRenderables.Sort(SortByIncreasingZOrder);
            foreach (IRenderable renderable in this.m_lstRenderables)
            {
                renderable.UpdateData(0.0f);
            }
        }

        virtual public void BeginRender()
        {
            this.m_effect.Device.VertexDeclaration = this.m_vertexDecl;
            this.m_effect.Technique = this.m_hTechnique;
            this.m_effect.Begin();
        }

        virtual public void RenderAllOpaques()
        {

        }

        virtual public void RenderAllTransparents()
        {

        }

        virtual public void Render(IRenderable _renderable)
        {

        }

        virtual public void EndRender()
        {
            this.m_effect.End();
        }

        virtual public void EndScene()
        {
            this.m_lstRenderables.Clear();
        }

        virtual public ManagedVertexBuffer<T> CreateBuffer<T>(int _sSize) where T : struct
        {
            return null;
        }

        virtual public void ReleaseBuffer<T>(ManagedVertexBuffer<T> _mVB) where T : struct
        {

        }

        virtual public IVertexFeeder CreateFeeder(int _sSize)
        {
            return null;
        }

        virtual public List<IVertexFeeder> CreateFeeders(IShape _shape)
        {
            return null;
        }

        virtual public void ReleaseFeeder(IVertexFeeder _vertexFeeder)
        {

        }

        virtual public void ReleaseFeeders(List<IVertexFeeder> _vertexFeeders)
        {
            foreach (IVertexFeeder feeder in _vertexFeeders)
            {
                ReleaseFeeder(feeder);
            }
            _vertexFeeders.Clear();
        }

        #endregion
    }
}
